#include <ez80F91.h>
#include <stdio.h>
#include "ZSysgen.h"
#include "ZTypes.h"
#include "ZThread.h"
#include "Types.h"
#include "eeprom.h"
#include "TimeControl.h"
#include "wlan_bssdef.h"
#include "netif.h"
#include "EtherMgr.h"
#include "ThreadControl.h"
#include "ZTimer.h"
#include <drv_types.h>
#include "rtl871x_event.h"
#include "wlan_stats.h"


extern INT16 Init_Wlan_Device(void);


extern INT8 f91_mac_addr[ETHPKT_ALEN];
extern NDIS_802_11_SSID g_Ssid;
extern struct netif	nif[];
extern INT8* eZ80_name;
extern UINT8 b_use_dhcp;

extern  INT16 joinNetwork(NDIS_802_11_SSID *connectSsid);
extern INT8 ConvertAsciiToWepArray( INT8 *pc_addr, UINT8 * wKey);
extern UINT8 wepKey[];
extern UINT8 wepKeyLen;
extern u8 g_maxAP;

#define WLAN_TIMER_PERIOD_S 30		//In seconds

//Timer Variables
extern TICK_t ticksPerSecond;
void WLANTimerFunction();
RZK_TIMERHANDLE_t WLANTimerHandle;
TICK_t WLANTimerInitialDelay = 0;
TICK_t WLANTimerPeriod;


#define WLAN_THREAD_STACK_SIZE          1024
#define WLAN_THREAD_PRIORITY            10      // This is the same as the default for the httpd
#define WLAN_THREAD_RR_TICKS            0       // This makes it use the default

//Thread variables
RZK_THREADHANDLE_t wlanThread;
CADDR_t g_WLANThreadStack[WLAN_THREAD_STACK_SIZE];
void WLANThreadEntry();



extern void networkInit(void);
extern UINT8  b_use_dhcp ;
extern BOOL	bootp_called;
extern void SpiderZInit( VOID ) ;

BOOL firstJoin;
BOOL WLANConnected = FALSE;


/* From rtl871x_event.h in RZK\Inc:
struct fwevent {
		u32	parmsize;
		void (*event_callback)(_adapter *dev, u8 *pbuf);
	};

struct fwevent	wlanevents[] = {
			{0, &survey_event_callback},
		{sizeof (struct surveydone_event), &surveydone_event_callback},
		{0, &joinbss_event_callback},
		{sizeof(struct stassoc_event), &stassoc_event_callback},
		{sizeof(struct stadel_event), &stadel_event_callback},
#ifdef CONFIG_PWRCTRL
		{0, &atimdone_event_callback},
#endif
};
*/
void WLANJoinNetwork();
void WLANDisconnectCallbackEvent(_adapter	*adapter, u8 *pbuf);
//Used as temporary workaround
void forceOldSchoolJoin();


struct fwevent WLANDisconnectEvent = {0, &WLANDisconnectCallbackEvent};

extern struct fwevent wlanevents[];
#define DISCONNECT_EVENT_INDEX 4

error_t WLANInit()
{
	eeprom_settings_t settings;

	//Overwrite callback funtion to use ours
	wlanevents[DISCONNECT_EVENT_INDEX] = WLANDisconnectEvent;

	//forceOldSchoolJoin();	
	firstJoin = TRUE;
	WLANJoinNetwork();
	firstJoin = FALSE;
	
	WLANTimerPeriod = ticksPerSecond * WLAN_TIMER_PERIOD_S;
	WLANTimerHandle = RZKCreateTimer(NULL, WLANTimerFunction, WLANTimerInitialDelay, WLANTimerPeriod);	

	if(WLANTimerHandle == NULL)
	{
		return GENERAL_ERROR;
	}

	return SUCCESS;
}


/*
 * Function to connect to WLAN and get current time from internet
 *
 * Params:
 *		none
 *
 * Returns:
 * 		none
 */
 error_t startWLANTimer()
 {
	if(RZKEnableTimer(WLANTimerHandle) != RZKERR_SUCCESS)
	{
		printf("Error creating WLAN timer\n");
		return GENERAL_ERROR;
	}
	else
	{
		printf("WLAN timer created successfully!\n");
		return SUCCESS;
	}
 }


/*
 * Function to connect to WLAN and get current time from internet
 *
 * Params:
 *		none
 *
 * Returns:
 * 		none
 */
void WLANTimerFunction()
{
	if(WLANConnected == FALSE)
	{
		WLANJoinNetwork();
	}
}



void WLANDisconnectCallbackEvent(_adapter	*adapter, u8 *pbuf)
{
	// We got disconnected
	printf("WLAN Disconnected!\n");
	WLANConnected = FALSE;
}


void WLANJoinNetwork()
{
	wlanThread = RZKCreateThread(
                (unsigned char *)  "WLANJoin",
                (RZK_PTR_t) &WLANThreadEntry,
                NULL, // Do we need a cleanup function because we may call this frequently?
                (CADDR_t)(g_WLANThreadStack + WLAN_THREAD_STACK_SIZE),
                WLAN_THREAD_PRIORITY,
                WLAN_THREAD_RR_TICKS,
                RZK_THREAD_ROUNDROBIN | RZK_THREAD_PREEMPTION | RZK_THREAD_AUTOSTART,
                0);

    if(wlanThread == NULL)
    {
		printf("Error creating WLAN thread: Code %i\n", RZKGetErrorNum());
    }
	else
	{
		//WLANConnected = TRUE; //But we don't really know that
	}
}

void WLANThreadEntry()
{
	eeprom_settings_t settings;

	if(firstJoin == TRUE && Init_Wlan_Device() < 0)
	{
		printf("Unable to initialize WLAN\n");
		return;
	}
	
	if (eepromGetSettings(&settings) == SUCCESS)
	{
		// Attempt to connect to our router
		g_Ssid.SsidLength = strlen(settings.wlanSettings.ssid);
		strcpy(g_Ssid.Ssid, settings.wlanSettings.ssid);
		strcpy(eZ80_name, "thermostat");

		//Set the WEP key (len = len/2 because 10 characters = 5 bytes and 26 characters = 13 bytes)
		wepKeyLen = settings.wlanSettings.wepKeyLen / 2;
		ConvertAsciiToWepArray((INT8 *)settings.wlanSettings.wepKey, wepKey);
		
		//Set found access points to 0
		g_maxAP = 0;
		printf("Scanning");
		sitesurvey_cmd(&g_Ssid);

		if(g_maxAP > 0 && joinNetwork(&g_Ssid) == 0)
		{
			printf("\nConnected to %s\n", g_Ssid.Ssid);
			WLANConnected = TRUE;
		}
		else
		{
			printf("\nUnable to connect to %s\n", g_Ssid.Ssid);
		}
		if(settings.timeSettings.internetTimeEnabled == TRUE)
		{
			if(getInternetTime() != SUCCESS)
			{
				printf("Unable to get internet time\n");
			}
		}
	}
	else
	{
		printf("Unable to initialize WLAN\n");
	}
}


void forceOldSchoolJoin()
{
	eeprom_settings_t settings;

	Init_Wlan_Device();

	if(eepromGetSettings(&settings) == SUCCESS)
	{
		// Attempt to connect to our router
		g_Ssid.SsidLength = strlen(settings.wlanSettings.ssid);
		strcpy(g_Ssid.Ssid, settings.wlanSettings.ssid);
		strcpy(eZ80_name, "thermostat");

		//Set the WEP key (len = len/2 because 10 characters = 5 bytes and 26 characters = 13 bytes)
		wepKeyLen = settings.wlanSettings.wepKeyLen / 2;
		ConvertAsciiToWepArray((INT8 *)settings.wlanSettings.wepKey, wepKey);
	
		//Set found access points to 0
		g_maxAP = 0;
		printf("Scanning");
		sitesurvey_cmd(&g_Ssid);

		if(joinNetwork(&g_Ssid) == 0)
		{
			WLANConnected = TRUE;
			printf("\nConnected to %s\n", g_Ssid.Ssid);
		}
		else
		{
			WLANConnected = FALSE;
			printf("\nUnable to connect to %s\n", g_Ssid.Ssid);
		}
		if(settings.timeSettings.internetTimeEnabled == TRUE)
		{
			if(getInternetTime() != SUCCESS)
			{
				printf("Unable to get internet time\n");
			}
		}
	}
}


/*
 * Function for the UI to call when a new network settings are saved
 */
void alertNewNetworkSettings()
{
	WLANConnected = FALSE;
}